package com.adlotto2.lcdns.util;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.ColorFilter;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.http.AndroidHttpClient;
import android.os.AsyncTask;
import android.util.Log;
import android.view.View;
import android.widget.ImageView;
import android.widget.ProgressBar;

import com.adlotto2.lcdns.R;
import com.adlotto2.lcdns.common.LottoAdFullActivity;

public class LottoAdImageDownloaderFile {
	public enum Mode { NO_ASYNC_TASK, NO_DOWNLOADED_DRAWABLE, CORRECT }
    private Mode mode = Mode.NO_ASYNC_TASK;
    
	private Context mContext = null;
	public Drawable loadingImage = null;
	public Drawable failImage = null;
	
	public final static int BUFFER_SIZE = 10240;
	
	/*
	 * 다운로드된 이미지를 저장할 경로
	 */
	private String CACHE_PATH = null;
	
	public LottoAdImageDownloaderFile(Context context) {
		this.mContext = context;
		
		// 다운로드 받을 경로 설정
		//CACHE_PATH = context.getFilesDir().getAbsolutePath() + "/image/";
		CACHE_PATH = context.getCacheDir().getAbsolutePath() + "/image/";
		
		// 경로 체크
		if(isExist(CACHE_PATH) == false) {
			CNCronosLog.d("folder do not exist, folder path=" + CACHE_PATH);
			createFolderIfNotExist(CACHE_PATH);
		} else {
			CNCronosLog.d("folder exist, folder path=" + CACHE_PATH);
		}
		
		// 캐쉬 폴더의 용량 체크(사용안함)
		//checkSpace(CACHE_PATH);
	}
	
	/*
	 * 이미지를 다운로드 한다. 로컬 디렉토리에 저장하며, 로컬 디렉토리에 존재할 경우 다운로드 하지 않는다.
	 * @param	[IN] url: 다운로드 할 url(예:http://182.173.191.166:8080/images/20120706/thumb_151136.JPG)
	 * 			[IN] imageView: 
	 * 			[IN] progressBar: 
	 * @return	이미지 캐쉬 여부(true: 이미지가 캐쉬 되어 있음, false: 이미지가 캐쉬 되지 않아 다운로드 해야함.
	 */
	public boolean download(String url, ImageView imageView, ProgressBar progressBar) {
		// url에서 파일 이름을 파싱한다.(파일 이름이 "시분초.jpg"이므로 상위 폴더부터 파일이름으로 처리하며, "/"는 "-"로 치환한다.)
		// 시분초만 가지고 처리하면 이미지가 중복될 수 있음.
		int index = url.lastIndexOf("/");
		index = url.lastIndexOf("/", index - 1);
		String filename = url.substring(index + 1);
		filename = filename.replace("/", "-");
		
		if(isExist(CACHE_PATH + filename) == true) {
			CNCronosLog.d("file exist, filepath=" + (CACHE_PATH + filename));
			Bitmap bitmap = LottoAdImageDownloaderFile.getBitmap(CACHE_PATH + filename);
			if(imageView != null) {
				
				imageView.setImageBitmap(bitmap);
//				imageView.setBackgroundDrawable(new BitmapDrawable(bitmap));
			}
			
			if(progressBar != null) {
				progressBar.setVisibility(View.GONE);
			}
			
			return true;
		} else {
			CNCronosLog.d("file do not exist, filepath=" + (CACHE_PATH + filename));
			if(progressBar != null) {
				progressBar.setVisibility(View.VISIBLE);
			}
			CNImageDownloaderTask task = new CNImageDownloaderTask(url, filename, imageView, progressBar);
			if(imageView != null) {
				DownloadedDrawable downloadedDrawable = new DownloadedDrawable(task);
				imageView.setImageDrawable(downloadedDrawable);
//				imageView.setBackgroundDrawable(downloadedDrawable);
			}
			task.execute(url, filename);
		}
		return false;
	}
	
	/*
	 * 폴더를 생성한다.
	 * @param	[IN] path: 생성할 경로
	 * @return	-
	 */
	public void createFolderIfNotExist(String path) {
		File file = new File(path);
		file.mkdirs();
	}
	
	/*
	 * 해당 폴더의 가용용량을 체크한다.
	 */
	/*
	public void checkSpace(String path) {
		File file = new File(path);
		CNCronosLog.d("check usable space=" + file.getUsableSpace() + ", total space=" + file.getTotalSpace());
	}
	*/
	
	/*
	 * 폴더 또는 파일이 존재하는 지 체크한다.
	 * @param	[IN] path: 폴더 또는 파일
	 * @return	TRUE: 존재함, FALSE: 존재하지 않음.
	 */
	public Boolean isExist(String path) {
		Boolean ret = false;
		File file = new File(path);
		ret = file.exists();
		return ret;
	}
	
	/*
	 * 로컬 디렉토리에 존재하는 이미지를 로드한다.
	 * @param	[IN] path: 로드할 이미지 경로
	 * @return	bitmap
	 */
	public static Bitmap getBitmap(String path) {
		Bitmap bitmap = null;
		InputStream is = null;
		try {
			is = new FileInputStream(path);
			bitmap = BitmapFactory.decodeStream(is);
			try {
				is.close();
				is = null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return bitmap;
	}
	
	class DownloadedDrawable extends BitmapDrawable {
		private final WeakReference<CNImageDownloaderTask> bitmapDownloaderTaskReference;

		public DownloadedDrawable(CNImageDownloaderTask bitmapDownloaderTask) {
			this.bitmapDownloaderTaskReference = new WeakReference<CNImageDownloaderTask>(
					bitmapDownloaderTask);
		}

		public CNImageDownloaderTask getBitmapDownloaderTask() {
			return bitmapDownloaderTaskReference.get();
		}

		@Override
		public void draw(Canvas canvas) {
			if (LottoAdImageDownloaderFile.this.loadingImage != null) {
				LottoAdImageDownloaderFile.this.loadingImage.setBounds(canvas
						.getClipBounds());
				LottoAdImageDownloaderFile.this.loadingImage.draw(canvas);
			}
		}

		public int getOpacity() {
			return 0;
		}

		public void setAlpha(int alpha) {
		}

		@Override
		public void setColorFilter(ColorFilter cf) {
		}
	}
	
	class CNImageDownloaderTask extends AsyncTask<String, Void, Boolean> {
		
		public String url;
		public String filename;
		public ProgressBar mProgressBar;
		private WeakReference<ImageView> imageViewReference;
		
		public CNImageDownloaderTask(String url, String filename, ImageView imageView, ProgressBar progressbar) {
			this.url = url;
			this.filename = filename;
			this.mProgressBar = progressbar;
			this.imageViewReference = new WeakReference<ImageView>(imageView);
		}

		@Override
		protected Boolean doInBackground(String... arg0) {
			// TODO Auto-generated method stub
			boolean ret = downloadBitmap(arg0[0], arg0[1]);
			return ret;
		}
		
		private CNImageDownloaderTask getBitmapDownloaderTask(ImageView imageView) {
			if (imageView != null) {
				Drawable drawable = imageView.getDrawable();
				if (drawable instanceof DownloadedDrawable) {
					DownloadedDrawable downloadedDrawable = (DownloadedDrawable) drawable;
					return downloadedDrawable.getBitmapDownloaderTask();
				}
			}
			return null;
		}
		
		/*
		 * web server로 부터 image을 다운로드 한다. 다운로드된 파일은 로컬 경로에 저장한다.
		 * @param	[IN] url: 다운로드 받을 URL
		 * 			[IN]filename: 다운로드 받은 데이타를 저장할 파일 이름
		 * @return	true: 성공, false: 실패
		 */
		private boolean downloadBitmap(String url, String filename) {
			CNCronosLog.d("image download url=" + url + ", Cache Path=" + CACHE_PATH + filename);
			
			final HttpClient client			= (mode == Mode.NO_ASYNC_TASK) ? 
		    		new DefaultHttpClient() : AndroidHttpClient.newInstance("Android");
		    		
		    final HttpGet getRequest 		= new HttpGet(url);
		    try 
		    {
		        HttpResponse response = client.execute(getRequest);
		        final int statusCode = response.getStatusLine().getStatusCode();
		        
		        if (statusCode != HttpStatus.SC_OK) 
		        {
		            return false;
		        }

		        final HttpEntity entity = response.getEntity();
		        if (entity != null) 
		        {
		            InputStream inputStream = null;
		         
		            try {
		            	inputStream = entity.getContent();
		            	
		            	// 다운로드 받은 데이타를 파일로 저장하기
		            	byte[] buffer = new byte[BUFFER_SIZE];
		            	String filePath = CACHE_PATH + filename;
		            	FileOutputStream fos = new FileOutputStream(filePath);
		            	BufferedInputStream bis = new BufferedInputStream(inputStream, BUFFER_SIZE);
		        		BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER_SIZE);
		        		int byteCnt=0;
		        		while((byteCnt = bis.read(buffer)) != -1){
		        			bos.write(buffer,0,byteCnt);
		        		}
		        		bis.close();
		        		inputStream.close();
		        		bos.flush();
		        		bos.close();
		        		fos.flush();
		        		fos.close();
		            	return true;
		            } catch (Exception e) {
						return false;
					} finally {
		                if (inputStream != null) 
		                {
		                    inputStream.close();
		                }
		                
		                entity.consumeContent();
		                return true;
		            }
		        }
		    } 
		    catch (IOException e) 
		    {
		        getRequest.abort();
		    } 
		    catch (IllegalStateException e) 
		    {
		        getRequest.abort();		    
		    } 
		    
		    
		    catch (Exception e) 
		    {
		        getRequest.abort();
		    } 
		    finally 
		    {
		        if ((client instanceof AndroidHttpClient)) 
		        {
		            ((AndroidHttpClient)client).close();
		        }
		    }
			
			return false;
		}
		
		/*
		 * @see android.os.AsyncTask#onPostExecute(java.lang.Object)
		 * @param	[IN] result: 이미지 다운로드 성공 여부(true: 성공, false: 실패)
		 */
		protected void onPostExecute(Boolean result) {
			if(isCancelled()) {
				
			}
			
			if (imageViewReference != null) {
				ImageView imageView = imageViewReference.get();
				CNImageDownloaderTask bitmapDownloaderTask = getBitmapDownloaderTask(imageView);
				
				if(this == bitmapDownloaderTask) {
					if(result == true) {
						Bitmap bitmap = LottoAdImageDownloaderFile.getBitmap(CACHE_PATH + filename);
						imageView.setImageBitmap(bitmap);
					} else { /*####### Ben ######## 다운로드실패시 기본 이미지 지정*/
						imageView.setBackgroundResource(R.drawable.image_download_fail);
					}
					
					if(mProgressBar != null) {
						mProgressBar.setVisibility(View.GONE);
					}
				}
			}
			
			if(mContext.getClass().getSimpleName().equals("LottoAdFullActivity")){
				((LottoAdFullActivity)mContext).imageDownloaded();
			}
		}
	}
}